package com.road.yishi.execaction;

import java.util.LinkedList;
import java.util.Queue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description :
 * @FileName: AbstractActionQueue.java
 * @Author :WeiHui.Zhang
 * @Data : 2016年2月1日 上午11:56:27
 * @Version:V1.00
 */
public class AbstractActionQueue implements ActionQueue {

	private static final Logger LOG = LoggerFactory.getLogger(AbstractActionQueue.class);
	private Queue<Action> queue;
	private Executor executor;

	public AbstractActionQueue(Executor executor) {
		this.executor = executor;
		this.queue = new LinkedList<Action>();
	}

	public AbstractActionQueue(Executor executor, Queue<Action> queue) {
		this.executor = executor;
		this.queue = queue;
	}

	@Override
	public ActionQueue getActionQueue() {
		return this;
	}

	@Override
	public void enqueue(Action action) {
		boolean canExec = false;
		synchronized (queue) {
			queue.add(action);
			if (queue.size() == 1) {
				canExec = true;
			} else if (queue.size() > 1000) {
				LOG.warn(action.toString() + " queue size : " + queue.size());
			}
		}
		if (canExec) {
			executor.execute(action);
		}
	}

	@Override
	public void enDelayQueue(DelayAction delayAction) {
		executor.enDelayQueue(delayAction);
	}

	@Override
	public void dequeue(Action action) {
		Action nextAction = null;
		synchronized (queue) {
			if (queue.size() == 0) {
				LOG.error("queue.size() is 0.");
			}
			// 将上个已经执行的命令从队列中移除
			// 移除并返回队列头部的元素 如果队列为空，则抛出一个NoSuchElementException异常
			Action temp = queue.remove();
			// 如果已经执行的action和要移除的temp不是同一个对象时
			if (temp != action) {
				LOG.error("action queue error. temp " + temp.toString() + ", action : " + action.toString());
			}
			if (queue.size() != 0) {
				nextAction = queue.peek();
			}
		}

		if (nextAction != null) {
			executor.execute(nextAction);
		}
	}

	@Override
	public void clear() {
		synchronized (queue) {
			queue.clear();
		}
	}

	@Override
	public Queue<Action> getQueue() {
		return queue;
	}

}
